/*
 * Manager.cpp
 *
 *  Created on: Aug 12, 2016
 *      Author: ubuntu
 */

#include "Manager.h"
#include <mysql++/mysql++.h>

#include "N900/N900Server.h"
#include "G2O/G2OServer.h"
#include "Cmd/CmdServer.h"
#include <libconfig.h++>
#include <pthread.h>
#include "Conf.h"
#include "common.h"

using namespace mysqlpp;
using namespace libconfig;


Manager::Manager()
{
	m_bTerminated = false;
	pManager = NULL;
}

Manager::~Manager()
{
	vector<TcpServer *>::iterator it = m_lstServers.begin();
	for (; it != m_lstServers.end(); it++) {
		TcpServer *pServer = *it;
		delete pServer;
	}
}

bool Manager::init()
{
	bool res = true;
	Config *pConfig = new Config();
	try {
		Conf *conf = getConf();
		pConfig->readFile(conf->path);
		Setting& setting = pConfig->lookup("receiver");
		for (int i = 0; i < setting.getLength(); i++) {
			string type;
			int port;
			if (setting[i].lookupValue("type", type)) {
				if (setting[i].lookupValue("port", port)) {
					if (type == "N900") {
						TcpServer *pServer = new N900Server(port, SV_N900);
						m_lstServers.push_back(pServer);
					} else if (type == "G2O") {
						TcpServer *pServer = new G2OServer(port, SV_G2O);
						m_lstServers.push_back(pServer);
					} else if (type == "cli") {
						TcpServer *pServer = new CmdServer(port, SV_CMD);
						m_lstServers.push_back(pServer);
					}
				}
			}
		}
	} catch (...) {
		res = false;
	}

	if (pConfig)
		delete pConfig;

//	pManager = new DBManager(getConf()->unix_path);
	pManager = getConf()->pManager;
	if (!pManager)
		return false;
	return res;
}

void Manager::start()
{
	pthread_t tid;
	vector<pthread_t> m_lstTid;
	vector<TcpServer *>::iterator it = m_lstServers.begin();
	for (; it != m_lstServers.end(); it++) {
		TcpServer *pServer = *it;
		pthread_create(&tid, NULL, Manager::ServerThread, (void *)pServer);
		m_lstTid.push_back(tid);
	}

	pthread_create(&tid, NULL, Manager::ClearThread, (void *)this);
	pthread_detach(tid);

	pthread_create(&tid, NULL, Manager::DataManage, (void *)pManager);
	pthread_join(tid, NULL);

	vector<pthread_t>::iterator itt = m_lstTid.begin();
	for (; itt != m_lstTid.end(); itt++) {
		pthread_t tid = *itt;
		pthread_join(tid, NULL);
	}
}


void Manager::stop()
{
	m_bTerminated = true;
	vector<TcpServer *>::iterator it = m_lstServers.begin();
	for (; it != m_lstServers.end(); it++) {
		TcpServer *pServer = *it;
		pServer->stop();
	}
	if (pManager)
		pManager->stop();
}

void *Manager::ServerThread(void *arg)
{
	TcpServer *pServer = (TcpServer *)arg;
	if (pServer->init())
		pServer->start();
	else
		exit(1);
	return NULL;
}

void *Manager::DataManage(void *arg)
{
	DBManager *pManager = (DBManager *)arg;
	pManager->run();
	return NULL;
}

void *Manager::ClearThread(void *arg)
{
	Manager *pManager = (Manager *)arg;
	pManager->clearClient();
	return NULL;
}

void Manager::clearClient()
{
	struct timespec ts;
	pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_cond_t cond_wait = PTHREAD_COND_INITIALIZER;

	while (!m_bTerminated) {
		update_logfile();
		vector<TcpServer *>::iterator it = m_lstServers.begin();
		for (; it != m_lstServers.end(); it++) {
			TcpServer *pServer = *it;
			pServer->clearClient();
		}
		ts.tv_sec = time(NULL) + 300;
		ts.tv_nsec = 0;
		pthread_mutex_lock(&cond_mutex);
		pthread_cond_timedwait(&cond_wait, &cond_mutex, &ts);
		pthread_mutex_unlock(&cond_mutex);
	}
}
